#region Copyright
/**
 *  This file is part of the Onix Solutions .NET FIX Engine Code Samples.
 *  
 *   Copyright (C) 2005-2012 Onix Solutions [OnixS].  All rights reserved.
 *  
 * This source code is intended only as a supplement to Onix Solutions
 * .NET FIX Engine and/or documentation. See these other materials 
 * for detailed information regarding Onix Solutions code samples.
 *  
 * THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 */
#endregion

using System;
using System.Collections.Generic;
using System.Diagnostics;
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.FIX42;
using Onixs.FixControls;

namespace OMS
{
    /// <summary>
    /// Orders collection.
    /// </summary>
    public class OrderBook
    {
        public Dictionary<string, Order> clientOrderID2order = new Dictionary<string, Order>();

        public OrderBook()
        {
        }        

        public void AddOrder(Order order)
        {
            lock (clientOrderID2order)
            {
                clientOrderID2order.Add(order.ClientOrderID, order);
            }
        }

        public Order UpdateOrder(Message executionReport)
        {
            Debug.Assert(MsgType.Execution_Report == executionReport.Type);           

            string clientOrderID = executionReport[Tags.ClOrdID];
            Order order;
            if(clientOrderID2order.ContainsKey(clientOrderID))
            {
                order = clientOrderID2order[clientOrderID];
                
            }
            else
            {
                string origClientOrderID = executionReport[Tags.OrigClOrdID];
                if (! string.IsNullOrEmpty(origClientOrderID) && clientOrderID2order.ContainsKey(origClientOrderID))
                {
                    order = clientOrderID2order[origClientOrderID];
                    order.OriginalClientOrderID = origClientOrderID;
                    order.ClientOrderID = clientOrderID;
                    lock (clientOrderID2order)
                    {
                        clientOrderID2order.Add(clientOrderID, order);
                    }
                    // write code to update trade based on tradeid. fPos sPos and sprPos
                }
                else
                {
                  // Trace.TraceWarning("Received Execution Report with unknown ClOrdID(11)=" + clientOrderID); // commented by MS
                   return null;
                }
            }            
             
            string lastPx = executionReport[Tags.LastPx];
            if (!string.IsNullOrEmpty(lastPx))
            {
                order.LastFillPrice = (long)double.Parse(lastPx, System.Globalization.CultureInfo.InvariantCulture);
            }

            string originalClientOrderID = executionReport[Tags.OrigClOrdID];
            if(! string.IsNullOrEmpty(originalClientOrderID))
            {
                order.OriginalClientOrderID = originalClientOrderID;
            }

            string cumQty = executionReport[Tags.CumQty];
            if (!string.IsNullOrEmpty(cumQty))
            {
                order.FilledQuantity = double.Parse(cumQty, System.Globalization.CultureInfo.InvariantCulture);
            }

            string orderID = executionReport[Tags.OrderID];
            if (!string.IsNullOrEmpty(orderID))
            {
                order.OrderID = orderID;
            }

            string orderStatus = executionReport[Tags.OrdStatus];
            order.Status = ParseFixOrderStatus(orderStatus);

            string text = executionReport[Tags.Text];
            if (!string.IsNullOrEmpty(text))
            {
                order.Text = text;
            }
            System.Diagnostics.Trace.WriteLine("MBX Update: Execution" + ";" + order.tradeID + ";" + order.ClientOrderID + ";" + order.Status + ";" + DateTime.Now + ";" + order.quantity + ";" + order.filledQuantity + ";" + order.Symbol + ";" + order.Price + ";" + order.Side + ";" + order.ToString());
            order.TransactTime = DateTime.Now;

            return order;
        }

        public Order FindOrderByClientOrderID(string clientOrderID)
        {
            if (clientOrderID2order.ContainsKey(clientOrderID))
             {
                 return clientOrderID2order[clientOrderID];
             }
            else
            {
                return null;
            }
        }

        private static Order.OrderStatus ParseFixOrderStatus(string ordStatus)
        {
            switch (ordStatus)
            {                   
                case "0":
                    return Order.OrderStatus.New;

                case "1":
                    return Order.OrderStatus.PartialFill;

                case "2":
                    return Order.OrderStatus.Fill;

                case "3":
                    return Order.OrderStatus.DoneForDay;

                case "4":
                    return Order.OrderStatus.Canceled;

                case "5":
                    return Order.OrderStatus.Replace;

                case "6":
                    return Order.OrderStatus.PendingCancel;

                case "7":
                    return Order.OrderStatus.Stopped;

                case "8":
                    return Order.OrderStatus.Rejected;

                case "9":
                    return Order.OrderStatus.Suspended;

                case "A":
                    return Order.OrderStatus.PendingNew;

                case "C":
                    return Order.OrderStatus.Calculated;

                case "D":
                    return Order.OrderStatus.Restated;

                case "E":
                    return Order.OrderStatus.PendingReplace;

                default:
                    throw new ApplicationException("Unsuppported order status: '" + ordStatus + "'");
            }
        }     
    }
}